'''
现有n个数,设计算法得到前k大的数 k<n
解决思路
1.排序后切片    O(nlogn)
2.排序lowb三人组 O(mn)
3.堆排序思路 O(nlogk)
'''

'''
找出1000个数中最大的前10
解决topk问题,
先建立小根堆,堆顶和列表k之后的进行比较,
替换比堆顶大的数,然后重新更新小根堆
....以此类推
'''


# 小根堆
def sift(li, low, high):
    i = low
    j = 2 * i + 1
    tmp = li[low]
    while j <= high:
        if j + 1 <= high and li[j + 1] < li[j]:
            j = j + 1
        if li[j] < tmp:
            li[i] = li[j]
            i = j
            j = i * 2 + 1
        else:
            break
        li[i] = tmp


def topk(li, k):
    heap = li[0:k]
    for i in range((k - 2) // 2, -1, -1):
        sift(heap, i, k - 1)
    # 建堆
    for i in range(k, len(li)-1):
        if li[i] > heap[0]:
            heap[0] = li[i]
            sift(heap, 0, k - 1)
    print(heap)
    # 遍历
    for i in range(k - 1, -1, -1):
        heap[0], heap[i] = heap[i], heap[0]
        sift(heap, 0, i - 1)
    # 出数
    return heap


import random

li = list(range(20))
random.shuffle(li)
print(li)
print(topk(li, 10))
